package com.gmcloud.upms.biz.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gmcloud.common.core.exception.BaseException;
import com.gmcloud.common.mybatis.base.BasePageEntity;
import com.gmcloud.common.mybatis.plus.QueryWrapperPlus;
import com.gmcloud.common.utils.BeanUtil;
import com.gmcloud.upms.api.system.entity.SysRole;
import com.gmcloud.upms.api.system.entity.dto.SysMenuDto;
import com.gmcloud.upms.api.system.entity.dto.SysRoleDto;
import com.gmcloud.upms.api.system.entity.payload.RoleQueryCriteria;
import com.gmcloud.upms.api.system.entity.vo.SysRoleVo;
import com.gmcloud.upms.api.system.entity.vo.menu.SysMenuVo;
import com.gmcloud.upms.biz.mapper.SysRoleMapper;
import com.gmcloud.upms.biz.service.SysMenuService;
import com.gmcloud.upms.biz.service.SysRoleService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zl.sir
 * @version 1.0
 * @since 2022/8/26 14:51
 * 角色操作实现类
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

    private final SysMenuService menuService;

    public SysRoleServiceImpl(SysMenuService menuService) {
        this.menuService = menuService;
    }

    @Override
    public List<SysRole> findListByUserId(Long userId) {
        return baseMapper.findListByUserId(userId);
    }

    @Override
    public Map<Long, List<SysRoleVo>> findMapByUserIds(List<Long> userIds) {
        List<SysRole> sysRoles = baseMapper.selectListByUserIds(userIds);
        List<SysRoleVo> sysRoleVos = BeanUtil.copyListProperties(sysRoles, SysRoleVo::new);
        return sysRoleVos.parallelStream().collect(Collectors.groupingByConcurrent(SysRoleVo::getUserId));
    }

    @Override
    public List<SysRoleVo> getRoles() {
        List<SysRole> roles = baseMapper.selectList(Wrappers.emptyWrapper());
        return BeanUtil.copyListProperties(roles, SysRoleVo::new);
    }

    @Override
    public BasePageEntity<SysRoleVo> page(Page<SysRole> iPage, RoleQueryCriteria queryCriteria) {
        Wrapper<SysRole> wrapper = QueryWrapperPlus.getPredicate(queryCriteria, SysRole::new);
        IPage<SysRole> page = baseMapper.selectPage(iPage, wrapper);
        List<SysRoleVo> sysRoleVos = BeanUtil.copyListProperties(page.getRecords(), SysRoleVo::new);
        if (!CollectionUtils.isEmpty(sysRoleVos)) {
            List<SysMenuVo> menuVos = menuService.findByRoleIds(sysRoleVos.stream().map(SysRoleVo::getId).toList());
            Map<Long, List<SysMenuVo>> listMap = menuVos.stream().collect(Collectors.groupingByConcurrent(SysMenuVo::getRoleId));
            sysRoleVos.forEach(sysRoleVo -> sysRoleVo.setMenus(listMap.get(sysRoleVo.getId())));
        }
        return new BasePageEntity<>(sysRoleVos, page.getTotal());
    }

    @Transactional(rollbackFor = BaseException.class)
    @Override
    public void saveRole(SysRoleDto sysRoleDto) {
        SysRole sysRole = new SysRole();
        BeanUtils.copyProperties(sysRoleDto, sysRole);
        baseMapper.insert(sysRole);

        if (!CollectionUtils.isEmpty(sysRoleDto.getMenus())) {
            List<SysMenuDto> sysMenuDtoList = sysRoleDto.getMenus();
            insertRoleAndMenus(sysRole.getId(), sysMenuDtoList.stream().map(SysMenuDto::getId).toList());
        }
    }

    @Transactional(rollbackFor = BaseException.class)
    @Override
    public void insertRoleAndMenus(Long roleId, List<Long> menuIds) {
        baseMapper.insertRoleAndMenus(roleId, menuIds);
    }

    @Transactional(rollbackFor = BaseException.class)
    @Override
    public void updateRole(SysRoleDto sysRoleDto) {
        SysRole sysRole = new SysRole();
        BeanUtils.copyProperties(sysRoleDto, sysRole);
        baseMapper.updateById(sysRole);

        if (!CollectionUtils.isEmpty(sysRoleDto.getMenus())) {
            deleteRoleAndMenus(sysRole.getId());
            insertRoleAndMenus(sysRole.getId(), sysRoleDto.getMenuIds());
        }
    }

    @Transactional(rollbackFor = BaseException.class)
    @Override
    public void deleteRoleAndMenus(Long roleId) {
        baseMapper.deleteRoleAndMenus(roleId);
    }

    @Transactional(rollbackFor = BaseException.class)
    @Override
    public void removeRole(SysRoleDto sysRoleDto) {
        deleteRoleAndMenus(sysRoleDto.getId());
        baseMapper.deleteById(sysRoleDto.getId());
    }
}
